﻿//********************************************************************
// 
//  file:  frmUploader.cs
// 
//  (C) Copyright 2010, Diomede Corporation
//  All rights reserved
// 
//  Use, modification, and distribution is subject to   
//  the New BSD License (See accompanying file license.txt).
// 
//********************************************************************

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Diomede.SDK;
using System.IO;
using System.Threading;

namespace Diomede.Explorer
{
    public partial class frmUploader : Form
    {
        public ISession Session { get; set; }
        public FolderNode mdNode { get; set; }

        Thread uploadthread = null;

        public frmUploader()
        {
            InitializeComponent();
        }

        public frmUploader(ISession session)
        {
            InitializeComponent();
            Session = session;
        }

        public frmUploader(ISession session, FolderNode node)
        {
            InitializeComponent();
            Session = session;
            mdNode = node;
        }

        private void btnOpenFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Multiselect = false;

            if (dlg.ShowDialog(this) == DialogResult.OK)
            {
                txtFile.Text = dlg.FileName;
                btnUpload_Click(sender, e);
            }


            
            
        }

        private void txtFile_DoubleClick(object sender, EventArgs e)
        {
            btnOpenFile_Click(sender, e);
        }

        private void btnCreateFile_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtFile.Text))
            {
                MessageBox.Show(this, "No selected file to upload.", "Upload");
                return;
            }

            IFileManagement f = Session as IFileManagement;
            ICreateFileExecResult result = f.CreateFile(txtFile.Text);
            if (result.Status == Diomede.SDK.Enums.ExecutionResults.Success)
            {
                MessageBox.Show(this, "File creation successful. FileID = " + result.FileID, "Create File");
            }
            else
            {
                MessageBox.Show(this, result.Message, "Create File Error");
            }
        }

        void setProgress(long current, long total)
        {
            this.BeginInvoke((ThreadStart)delegate()
            {
                pb.Minimum = 0;
                pb.Maximum = 100;
                pb.Value = (int)(((double)current / (double)total) * 100);
                lblPercent.Text = pb.Value + " %";
                this.Refresh();
            });
        }

        void ShowMessage(string caption, string message)
        {
            this.BeginInvoke((ThreadStart)delegate()
            {
                MessageBox.Show(this, message, caption);
            }); 
        }

        void ResetButtons()
        {
            this.BeginInvoke((ThreadStart)delegate()
            {
                btnUpload.Enabled = true;
                btnCancel.Enabled = false;
                btnOpenFile.Enabled = true;
                chkAdvanced.Enabled = true;
            });
        }

        private void ChunkUpload()
        {
            IFileManagement f = Session as IFileManagement;

            ICreateFileExecResult createResult = f.CreateFile(txtFile.Text);
            if (createResult.Status != Diomede.SDK.Enums.ExecutionResults.Success)
            {
                ShowMessage("File Creation error.",createResult.Message);
                ResetButtons();
                return;
            }
            long fileID = createResult.FileID;

            int chunkSize = 51200;
            using (FileStream stream = File.Open(txtFile.Text, FileMode.Open, FileAccess.Read))
            {
                if (chunkSize > stream.Length)
                    chunkSize = (int)stream.Length;

                byte[] buffer = new byte[chunkSize];
                int bufferLen = 0;
                long uploaded = 0;
                long offset = 0;
                bool isComplete = false;
                while (true)
                {
                    setProgress(uploaded, stream.Length);

                    bufferLen = stream.Read(buffer, 0, chunkSize);
                    if (bufferLen == 0)
                        break;


                    if (bufferLen < buffer.Length)
                        Array.Resize<byte>(ref buffer, bufferLen);

                    uploaded += bufferLen;
                    isComplete = uploaded == stream.Length;

                    if (f.Upload(fileID, new MemoryStream(buffer), offset, isComplete).Status != Diomede.SDK.Enums.ExecutionResults.Success)
                    {
                        ShowMessage("File upload.","Upload error");
                        stream.Close();
                        ResetButtons();
                        return;
                    }

                    if (isComplete)
                        break;

                    offset = uploaded;
                }
            }

            setProgress(10, 10);
            ShowMessage("File Upload","File uploading successful.");
            setupMetaData(fileID);
            this.BeginInvoke((ThreadStart)delegate()
            {
                this.DialogResult = DialogResult.OK;
            });
        }

        

        private void btnUpload_Click(object sender, EventArgs e)
        {
            btnUpload.Enabled = false;
            btnCancel.Enabled = true;
            btnOpenFile.Enabled = false;
            chkAdvanced.Enabled = false;
            if (string.IsNullOrEmpty(txtFile.Text))
            {
                MessageBox.Show(this, "No selected file to upload.", "Upload");
                btnUpload.Enabled = true;
                btnCancel.Enabled = false;
                btnOpenFile.Enabled = true;
                chkAdvanced.Enabled = true;
                return;
            }

            Thread r = new Thread(new ThreadStart(ChunkUpload));
            r.IsBackground = true;
            uploadthread = r;
            r.Start();

        }

        private void btnUploadFull_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtFile.Text))
            {
                MessageBox.Show(this, "No selected file to upload.", "Upload");
                return;
            }
            IFileManagement f = Session as IFileManagement;
            IUploadExecResult result = f.Upload(txtFile.Text);
            if (result.Status != Diomede.SDK.Enums.ExecutionResults.Success)
            {
                MessageBox.Show(this, result.Message, "Upload");
            }
            else
            {
                MessageBox.Show(this, "Upload successful.", "Upload");
                setupMetaData(result.FileID);
                this.DialogResult = DialogResult.OK;
            }
        }

        void setupMetaData(long fileID)
        {
            if (mdNode != null)
            {
                IFileManagement f = Session as IFileManagement;
                IStoredFile file = f.StoredFileInstance(fileID);
                file.AddMetaData(mdNode.MetaData.metaDataID);
            }
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {

            if (uploadthread.IsAlive) uploadthread.Abort();
            btnUpload.Enabled = true;
            btnCancel.Enabled = false;
            btnOpenFile.Enabled = true;
            chkAdvanced.Enabled = true;
            lblPercent.Text = "";
            pb.Value = 0;

        }

        private void frmUploader_Load(object sender, EventArgs e)
        {
            
        }

        private void frmUploader_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (uploadthread != null && uploadthread.IsAlive) uploadthread.Abort();
        }

        private void tmrStart_Tick(object sender, EventArgs e)
        {
            tmrStart.Stop();
            btnOpenFile_Click(sender, e);

        }

        private void chkAdvanced_CheckedChanged(object sender, EventArgs e)
        {
            if (chkAdvanced.Checked)
            {
                this.Height = this.Height + 47;
            }
            else
            {
                this.Height = this.Height - 47;
            }
        }

    }
}
